package calao.client;

import calao.client.ui.HasDeferredLoading;
import calao.client.ui.HasLinks;
import calao.client.ui.Link;

import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.WindowResizeListener;

import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.HorizontalSplitPanel;

public class DesktopPanel
extends VerticalPanel
implements WindowResizeListener
{

	static final String SPLASH_PANEL_STYLE = "calao-SplashPanel";

	static class LoadingSplashPanel extends Grid {
		LoadingSplashPanel() {
			super(1,1);
			addStyleName(SPLASH_PANEL_STYLE);
			setWidget(0, 0, new Image("loading.gif"));
		}
	}

	final VerticalPanel adminLinks = new VerticalPanel();
	final VerticalPanel searchLinks = new VerticalPanel();

	final Desktop desktop;
	final HorizontalPanel top;
	final ShortcutsPanel shortcutsPanel;
	final HorizontalSplitPanel main;

	final Timer checkSplitterTask = new Timer() {
		public void run() {
			checkMainSplitPosition();
		}
	};

	ViewPanel view;

	DesktopPanel(Desktop desktop, SessionInfo session)
	{
		this.desktop = desktop;
		top = new HorizontalPanel();
		top.addStyleName("calao-TopLinkPanel");
		Label userAlias = new Label(session.userName);
		userAlias.addStyleName("calao-userAlias");
		top.add(userAlias);
		add(top);
		main = new HorizontalSplitPanel();
		shortcutsPanel = new ShortcutsPanel(desktop);
		shortcutsPanel.setWidth("100%");
		main.setLeftWidget(shortcutsPanel);
		main.setSplitPosition("25%");
		main.setWidth("100%");
		add(main);
		setWidth("100%");
		// top links
		Link[] topLinks = buildTopLinks();
		for (int i=0; i<topLinks.length; i++) {
			final Link link = topLinks[i];
			Label separator = new Label("|");
			separator.addStyleName("calao-TopLinkSeparator");
			top.add(separator);
			top.add(link);
		}
		addBaseLinks();
		Window.addWindowResizeListener(this);
		DeferredCommand.addCommand(new Command() {
			public void execute() {
				displayShortcuts();
				onWindowResized(Window.getClientWidth(), Window.getClientHeight());
			}
		});
	}

	protected void onLoad()
	{
		checkSplitterTask.scheduleRepeating(350);		
	}

	protected void onUnload()
	{
		checkSplitterTask.cancel();		
	}

	void checkMainSplitPosition()
	{
		int leftWidth = DOM.getElementPropertyInt(
				DOM.getFirstChild(DOM.getFirstChild(main.getElement())), 
		"offsetWidth");
		shortcutsPanel.setWidth(leftWidth);
	}

	void setView(final Widget widget, final String title, final boolean stacked)
	{
		if (widget instanceof HasDeferredLoading && ServiceCallback.getPendingCallCount()>0) {
			if (!(main.getRightWidget() instanceof LoadingSplashPanel)) {
				main.setRightWidget(new LoadingSplashPanel());
			}
			ServiceCallback.defer(new Command() {
				public void execute() {
					setView(widget, title, stacked);
				}
			});
		}
		else {
			view = new ViewPanel(widget, title, stacked? view : null);
			if (widget instanceof HasLinks) {
				Link[] links = ((HasLinks)widget).getLinks();
				for (int i=0; i<links.length; i++) view.addLink(links[i], "»");
			}
			for (int i=0; i<desktop.listeners.size(); i++) {
				((DesktopListener)desktop.listeners.get(i)).onDisplay(view);
			}
			if (view.parent!=null) {
				if (view.getLinkCount()>0) view.addLinkSpacer();
				view.addLink(view.parent.nextBackLink, "«");			
			}
			main.setRightWidget(view);
		}
	}

	void popView()
	{
		view = view.parent;
		main.setRightWidget(view);
	}
	
	void refreshView(Widget widget)
	{
		ViewPanel view = this.view;
		while (view!=null) {
			if (view.content==widget) {
				view.refresh();
				break;
			}
			view = view.parent;
		}
	}

	public void onWindowResized(int width, int height) 
	{
		int mainHeight = height - main.getAbsoluteTop() - 8;
		if (mainHeight<1) mainHeight = 1;
		int mainWidth = width - main.getAbsoluteLeft() - 8;
		if (mainWidth<1) mainWidth = 1;
		String mainHeightStr = Integer.toString(mainHeight);
		String mainWidthStr = Integer.toString(mainWidth);
		main.setSize(mainWidthStr, mainHeightStr);
		shortcutsPanel.setHeight(mainHeight);
		// main.getLeftWidget().setHeight(mainHeightStr);
		desktop.log("Desktop panel new size: "+mainWidth+"x"+mainHeight);
	}

	private void displayShortcuts()
	{
		Shortcut[] shortcuts = desktop.listActiveShortcuts();
		for (int i=0; i<shortcuts.length; i++) {
			try {
				Shortcut shortcut = shortcuts[i];
				if (!shortcut.inited) {
					shortcut.init();
					shortcut.inited = true;
				}
				shortcutsPanel.addShortcut(shortcut);
				desktop.log("Added shortcut "+shortcut.getName());
			}
			catch (Exception e) {
				desktop.log(e);
			}
		}		
	}

	private Link[] buildTopLinks()
	{
		Link admin = new Link(desktop.text.administration()) {
			public void onClick() {
				setView(adminLinks, 
						desktop.text.administration(), false);
			}
		};
		Link prefs = new Link(desktop.text.preferences()) {
			public void onClick() {
				setView(new PreferencesPanel(desktop, false), 
						desktop.text.preferences(), false);
			}
		};
		Link logout = new Link(desktop.text.logout()) {
			public void onClick() {
				desktop.logout();
			}
		};
		if (desktop.has(SessionService.ADMIN)) return new Link[] { admin, prefs, logout };
		else return new Link[] {prefs, logout};
	}

	public void addAdminLink(Link link)
	{
		adminLinks.add(link);
	}

	public void addSearchLink(Link link)
	{
		searchLinks.add(link);
	}

	public void addStartLink(Link link)
	{
		desktop.startShortcut.getMenuPanel().add(link);
	}

	private void addBaseLinks()
	{
		addStartLink(new Link(desktop.text.search()) {
			protected void onClick() {
				setView(searchLinks, desktop.text.search(), false);
			}
		});
		addAdminLink(new Link(desktop.text.workspacePreferences()) {
			public void onClick() {
				setView(new PreferencesPanel(desktop, true), null, true);
			}
		});			
		if (desktop.has(MemberService.ADMIN_MEMBERS)) {
			addAdminLink(new Link(desktop.text.users()) {
				public void onClick() {
					setView(new UserAdminPanel(DesktopPanel.this), null, true);
				}
			});				
		}
		addAdminLink(new Link(desktop.text.history()) {
			public void onClick() {
				setView(new HistoryPanel(desktop), desktop.text.history(), true);
			}
		});				
	}

}
